﻿using System;

namespace Klinkby.PipesAndFilters
{
    public class ComboFilter<T1, T2, T3, T4> : IFilter<T1, T4>
    {
        IFilter<T1, T2> _f1;
        IFilter<T2, T3> _f2;
        IFilter<T3, T4> _f3;

        public ComboFilter(IFilter<T1, T2> f1, IFilter<T2, T3> f2, IFilter<T3, T4> f3)
        {
            if (f1 == null)
                throw new ArgumentNullException("f1");
            if (f2 == null)
                throw new ArgumentNullException("f2");
            if (f3 == null)
                throw new ArgumentNullException("f3");
            _f1 = f1;
            _f2 = f2;
            _f3 = f3;
        }

        public static IFilter<T1, T4> Create(IFilter<T1, T2> f1, IFilter<T2, T3> f2, IFilter<T3, T4> f3)
        {
            return new ComboFilter<T1, T2, T3, T4>(f1, f2, f3);
        }

        public T4 Process(T1 value)
        {
            return _f3.Process(_f2.Process(_f1.Process(value)));
        }

        public bool CanProcess(T1 value)
        {
            return _f1.CanProcess(value);
        }

        #region Dispose
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                _f1.Dispose();
                _f2.Dispose();
                _f3.Dispose();
            }
        }
        public void Dispose()
        {
            GC.SuppressFinalize(this);
            Dispose(true);
        }
        ~ComboFilter()
        {
            Dispose(false);
        }
        #endregion
    }
}
